package com.pluser.mq.engine;

import java.io.IOException;

import com.ibm.mq.MQException;
import com.ibm.mq.MQGetMessageOptions;
import com.ibm.mq.constants.MQConstants;
import com.pluser.mq.vo.QueueInfo;
import com.pluser.mq.vo.QueueManagerInfo;

/**
 * 
 * Abstract listener class
 * @author pluser
 * @version 1.0
 * @date 2014-05-03
 * @modifiedHis
 *
 * @description
 * listener queue and handle get message from queue
 */
public abstract class AbstractListener {

	public static final int MQOO_DEFAULT = 	MQConstants.MQOO_INPUT_SHARED
			| MQConstants.MQOO_FAIL_IF_QUIESCING;
	public static final int MQOO_BROWSE = MQConstants.MQOO_BROWSE
			| MQConstants.MQOO_FAIL_IF_QUIESCING;
	public static final int MQGMO_DEFAULT = MQConstants.MQGMO_WAIT
			| MQConstants.MQGMO_FAIL_IF_QUIESCING;
	public static final int MQGMO_BROWSE = MQConstants.MQGMO_BROWSE_NEXT
			| MQConstants.MQGMO_WAIT | MQConstants.MQGMO_FAIL_IF_QUIESCING;
	
	private Receiver receiver;
	private MQGetMessageOptions gmo;
	private boolean isTerminate;
	
	/**
	 * constructor
	 * @param qmInfo 
	 * @param qName qName name of queue
	 * @param isRemove
	 * @throws MQException
	 */
	protected AbstractListener(QueueManagerInfo qmInfo, String qName, boolean isRemove)
			throws MQException {
		
		receiver = new Receiver(qmInfo, getQueueInfo(qName, isRemove));
		gmo = new MQGetMessageOptions();
		gmo.waitInterval = MQConstants.MQWI_UNLIMITED;
		
		if(isRemove) {
			gmo.options = MQGMO_DEFAULT;
		} else {
			
			gmo.options = MQGMO_BROWSE;
		}
		
		isTerminate = false;
	}
	
	/**
	 * get queue info
	 * @param qName qName name of queue
	 * @param isRemove get message whether remove this message from queue
	 * @return
	 */
	private QueueInfo getQueueInfo(String qName, boolean isRemove) {
		
		QueueInfo qInfo = new QueueInfo(qName);
		
		if(isRemove) {
			qInfo.setOpenOptions(MQOO_DEFAULT);
		} else {
			qInfo.setOpenOptions(MQOO_BROWSE);
		}
		
		return qInfo;
	}
	
	/**
	 * terminate listening queue
	 */
	public void terminate() {
		isTerminate = true;
	}
	
	/**
	 * listener whether is terminated
	 * @return
	 */
	public boolean isTerminate() {
		return isTerminate;
	}
	
	/**
	 * start listen queue
	 * @throws MQException
	 * @throws IOException
	 */
	public void startListen() throws IOException, MQException {
		
		byte[] msg = null;
		
		try {
			
			while(!isTerminate) {
				
				msg = receiver.getMsg(gmo);
				handleMsg(msg);
			} 
		} finally {
			if(receiver != null) {
				receiver.disconnect();
			}
		}
	}
	
	/**
	 * handle message from receive queue
	 * @param msg message from queue
	 */
	public abstract void handleMsg(byte[] msg);
}
